/****************************************************************************
 * Copyright 2009 Huascar A. Sanchez                                        *
 *                                                                          *
 * Licensed under the Apache License, Version 2.0 (the "License");          *
 * you may not use this file except in compliance with the License.         *
 * You may obtain a copy of the License at                                  *
 *                                                                          *
 *     http://www.apache.org/licenses/LICENSE-2.0                           *
 *                                                                          *
 * Unless required by applicable law or agreed to in writing, software      *
 * distributed under the License is distributed on an "AS IS" BASIS,        *
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. *
 * See the License for the specific language governing permissions and      *
 * limitations under the License.                                           *
 ****************************************************************************/
package com.gotobject.filter.spi;

import static com.gotobject.filter.spi.XmlBuilder.*;
import com.gotobject.filter.xml.XmlFilterTest;
import static com.gotobject.filter.XmlFilterQ.from;
import org.junit.After;
import static org.junit.Assert.*;
import org.junit.Before;
import org.junit.Test;
import org.w3c.dom.Comment;
import org.w3c.dom.Document;
import org.w3c.dom.Node;
import org.w3c.dom.Text;

import java.net.URL;

/**
 * @author huascar.sanchez@gmail.com (Huascar A. Sanchez)
 */
public class XmlBuilderTest {
    private String xmlVersion;

    @Before
    public void setUp() throws Exception {
        xmlVersion = "1.0";
    }

    @After
    public void tearDown() throws Exception {
        xmlVersion = null;
    }


    @Test
    public void emptyDocument(){
        final Document doc = document();
        assertNotNull(doc);
    }

    @Test
    public void nonEmptyDocument() throws Exception {
        final URL       path    = XmlFilterTest.class.getResource("Person.xml");
        final Document  doc     = document(path);

        assertNotNull(doc);
        assertTrue(doc.getChildNodes().getLength() > 0);
    }

    @Test
    public void oneVersioned_And_StandaloneDocument() throws Exception {
        final Document doc = document(xmlVersion, true);

        assertEquals(xmlVersion, doc.getXmlVersion());
        assertTrue(doc.getXmlStandalone());
    }

    @Test
    public void oneDocument_CommentedElement() throws Exception {
        final Document doc = document(comment("This is the Cars element."));
        final Comment subject = (Comment) doc.getFirstChild();
        assertEquals("This is the Cars element.", subject.getTextContent());
    }

    @Test
    public void oneDocument_WithEmptyChildElement() throws Exception {
        final Document doc = document(element("Cars", element("Car")));

        final Node parent  = doc.getFirstChild();
        final Node child   = parent.getFirstChild();

        assertNotNull(child);
        assertTrue(parent.getChildNodes().getLength() == 1);
        assertEquals("Car", child.getNodeName());
    }

    @Test
    public void oneDocument_WithChildElement_WithContent() throws Exception {
        final Document doc = document(element("Cars", element("Car", "Toyota Matrix")));

        final Node parent = doc.getFirstChild();
        final Node child  = parent.getFirstChild();

        assertNotNull(child);
        assertTrue(parent.getChildNodes().getLength() == 1);
        assertEquals("Car", child.getNodeName());
        assertEquals("Toyota Matrix", child.getTextContent());
    }

    @Test
    public void oneDocument_WithChildElement_WithOneAttribute() throws Exception {
        final Document  doc     = document(element("Cars", attribute("make", "Honda Accord")));
        final Node      child   = doc.getFirstChild();

        final Node attr =  child.getAttributes().item(0);

        assertNotNull(attr);
        assertTrue(child.getAttributes().getLength() == 1);
        assertEquals("make", attr.getNodeName());
        assertEquals("Honda Accord", attr.getNodeValue());
    }
    

    @Test
    public void oneDocument_WithRootElement(){
        final Document doc = document(element("Cars"));

        assertNotNull(doc.getFirstChild());
        assertEquals("Cars", doc.getFirstChild().getNodeName());
    }

    @Test
    public void oneDocument_WithTextElement() throws Exception {
        final Document doc     = document(element("Flags", text("why did we use flags?")));

        final Node     parent  = doc.getFirstChild();
        final Text     text    = (Text) parent.getFirstChild();

        assertEquals("why did we use flags?", text.getTextContent());
    }

    @Test
    public void oneDocument_WithCheckedOutput() throws Exception {
        final String expected = "<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"no\"?><!--This is the Cars element.-->";
        final Document doc = document(comment("This is the Cars element."));

        final String received = output(doc);

        assertEquals(expected, received);
        System.out.println(received);
    }


    @Test
    public void oneDocumentsElements_FromAnotherDocumentsElements() throws Exception {
        final URL       path      = XmlFilterTest.class.getResource("Person.xml");
        final Document  base      = document(path);

        final Document  generated = document(
                                element("Cars-ownership",
                                        from(Xml.doc(base))
                                                .elements("ownership").select()
                                )
        );

        final String received = output(generated);
        System.out.println(received);
    }

    @Test
    public void oneStandaloneDocument() throws Exception {
        final Document doc = document(true);  // no elements
        assertTrue(doc.getXmlStandalone());
    }

    @Test
    public void oneStandaloneDocument_WithRootElement() throws Exception {
        final Document doc  = document(true, element("Cars"));  // with one element

        assertTrue(doc.getXmlStandalone());
        assertEquals("Cars", doc.getFirstChild().getNodeName());
        assertTrue(doc.getChildNodes().getLength() == 1);
    }

    @Test
    public void oneVersionedDocument() throws Exception {
        final Document doc = document(xmlVersion);

        assertEquals(xmlVersion, doc.getXmlVersion());
        assertTrue(doc.getChildNodes().getLength() == 0);
    }

    @Test
    public void oneVersionedDocument_WithRootElement() throws Exception {
        final Document doc = document(xmlVersion, element("Cars"));

        assertEquals(xmlVersion, doc.getXmlVersion());
        assertEquals("Cars", doc.getFirstChild().getNodeName());
        assertTrue(doc.getChildNodes().getLength() == 1);
    }


    @Test
    public void oneVersioned_And_StandaloneDocument_WithRootElement() throws Exception {
        final Document doc = document(xmlVersion, true, element("Cars"));

        assertEquals(xmlVersion, doc.getXmlVersion());
        assertTrue(doc.getXmlStandalone());
        assertEquals("Cars", doc.getFirstChild().getNodeName());
        assertTrue(doc.getChildNodes().getLength() == 1);
    }
}